1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 package java.awt.color;
37
38 import sun.java2d.cmm.PCMM;
39 import sun.java2d.cmm.CMSManager;
40 import sun.java2d.cmm.ProfileDeferralMgr;
41 import sun.java2d.cmm.ProfileDeferralInfo;
42 import sun.java2d.cmm.ProfileActivator;
43
44 import java.io.File;
45 import java.io.FileInputStream;
46 import java.io.FileNotFoundException;
47 import java.io.FileOutputStream;
48 import java.io.IOException;
49 import java.io.InputStream;
50 import java.io.ObjectInputStream;
51 import java.io.ObjectOutputStream;
52 import java.io.ObjectStreamException;
53 import java.io.OutputStream;
54 import java.io.Serializable;
55
56 import java.util.StringTokenizer;
57
58 import java.security.AccessController;
59 import java.security.PrivilegedAction;
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 public class ICC_Profile implements Serializable {
93
94 private static final long serialVersionUID = -3938515861990936766L;
95
96 transient long ID;
97
98 private transient ProfileDeferralInfo deferralInfo;
99 private transient ProfileActivator profileActivator;
100
101
102
103
104 private static ICC_Profile sRGBprofile;
105 private static ICC_Profile XYZprofile;
106 private static ICC_Profile PYCCprofile;
107 private static ICC_Profile GRAYprofile;
108 private static ICC_Profile LINEAR_RGBprofile;
109
110
111
112
113
114 public static final int CLASS_INPUT = 0;
115
116
117
118
119 public static final int CLASS_DISPLAY = 1;
120
121
122
123
124 public static final int CLASS_OUTPUT = 2;
125
126
127
128
129 public static final int CLASS_DEVICELINK = 3;
130
131
132
133
134 public static final int CLASS_COLORSPACECONVERSION = 4;
135
136
137
138
139 public static final int CLASS_ABSTRACT = 5;
140
141
142
143
144 public static final int CLASS_NAMEDCOLOR = 6;
145
146
147
148
149
150 public static final int icSigXYZData = 0x58595A20;
151
152
153
154
155 public static final int icSigLabData = 0x4C616220;
156
157
158
159
160 public static final int icSigLuvData = 0x4C757620;
161
162
163
164
165 public static final int icSigYCbCrData = 0x59436272;
166
167
168
169
170 public static final int icSigYxyData = 0x59787920;
171
172
173
174
175 public static final int icSigRgbData = 0x52474220;
176
177
178
179
180 public static final int icSigGrayData = 0x47524159;
181
182
183
184
185 public static final int icSigHsvData = 0x48535620;
186
187
188
189
190 public static final int icSigHlsData = 0x484C5320;
191
192
193
194
195 public static final int icSigCmykData = 0x434D594B;
196
197
198
199
200 public static final int icSigCmyData = 0x434D5920;
201
202
203
204
205 public static final int icSigSpace2CLR = 0x32434C52;
206
207
208
209
210 public static final int icSigSpace3CLR = 0x33434C52;
211
212
213
214
215 public static final int icSigSpace4CLR = 0x34434C52;
216
217
218
219
220 public static final int icSigSpace5CLR = 0x35434C52;
221
222
223
224
225 public static final int icSigSpace6CLR = 0x36434C52;
226
227
228
229
230 public static final int icSigSpace7CLR = 0x37434C52;
231
232
233
234
235 public static final int icSigSpace8CLR = 0x38434C52;
236
237
238
239
240 public static final int icSigSpace9CLR = 0x39434C52;
241
242
243
244
245 public static final int icSigSpaceACLR = 0x41434C52;
246
247
248
249
250 public static final int icSigSpaceBCLR = 0x42434C52;
251
252
253
254
255 public static final int icSigSpaceCCLR = 0x43434C52;
256
257
258
259
260 public static final int icSigSpaceDCLR = 0x44434C52;
261
262
263
264
265 public static final int icSigSpaceECLR = 0x45434C52;
266
267
268
269
270 public static final int icSigSpaceFCLR = 0x46434C52;
271
272
273
274
275
276 public static final int icSigInputClass = 0x73636E72;
277
278
279
280
281 public static final int icSigDisplayClass = 0x6D6E7472;
282
283
284
285
286 public static final int icSigOutputClass = 0x70727472;
287
288
289
290
291 public static final int icSigLinkClass = 0x6C696E6B;
292
293
294
295
296 public static final int icSigAbstractClass = 0x61627374;
297
298
299
300
301 public static final int icSigColorSpaceClass = 0x73706163;
302
303
304
305
306 public static final int icSigNamedColorClass = 0x6e6d636c;
307
308
309
310
311
312 public static final int icPerceptual = 0;
313
314
315
316
317 public static final int icRelativeColorimetric = 1;
318
319
320
321
322
323 public static final int icMediaRelativeColorimetric = 1;
324
325
326
327
328 public static final int icSaturation = 2;
329
330
331
332
333 public static final int icAbsoluteColorimetric = 3;
334
335
336
337
338
339 public static final int icICCAbsoluteColorimetric = 3;
340
341
342
343
344
345 public static final int icSigHead = 0x68656164;
346
347
348
349
350 public static final int icSigAToB0Tag = 0x41324230;
351
352
353
354
355 public static final int icSigAToB1Tag = 0x41324231;
356
357
358
359
360 public static final int icSigAToB2Tag = 0x41324232;
361
362
363
364
365 public static final int icSigBlueColorantTag = 0x6258595A;
366
367
368
369
370
371 public static final int icSigBlueMatrixColumnTag = 0x6258595A;
372
373
374
375
376 public static final int icSigBlueTRCTag = 0x62545243;
377
378
379
380
381 public static final int icSigBToA0Tag = 0x42324130;
382
383
384
385
386 public static final int icSigBToA1Tag = 0x42324131;
387
388
389
390
391 public static final int icSigBToA2Tag = 0x42324132;
392
393
394
395
396 public static final int icSigCalibrationDateTimeTag = 0x63616C74;
397
398
399
400
401
402 public static final int icSigCharTargetTag = 0x74617267;
403
404
405
406
407 public static final int icSigCopyrightTag = 0x63707274;
408
409
410
411
412 public static final int icSigCrdInfoTag = 0x63726469;
413
414
415
416
417 public static final int icSigDeviceMfgDescTag = 0x646D6E64;
418
419
420
421
422 public static final int icSigDeviceModelDescTag = 0x646D6464;
423
424
425
426
427 public static final int icSigDeviceSettingsTag = 0x64657673;
428
429
430
431
432 public static final int icSigGamutTag = 0x67616D74;
433
434
435
436
437 public static final int icSigGrayTRCTag = 0x6b545243;
438
439
440
441
442 public static final int icSigGreenColorantTag = 0x6758595A;
443
444
445
446
447
448 public static final int icSigGreenMatrixColumnTag = 0x6758595A;
449
450
451
452
453 public static final int icSigGreenTRCTag = 0x67545243;
454
455
456
457
458 public static final int icSigLuminanceTag = 0x6C756d69;
459
460
461
462
463 public static final int icSigMeasurementTag = 0x6D656173;
464
465
466
467
468 public static final int icSigMediaBlackPointTag = 0x626B7074;
469
470
471
472
473 public static final int icSigMediaWhitePointTag = 0x77747074;
474
475
476
477
478 public static final int icSigNamedColor2Tag = 0x6E636C32;
479
480
481
482
483 public static final int icSigOutputResponseTag = 0x72657370;
484
485
486
487
488 public static final int icSigPreview0Tag = 0x70726530;
489
490
491
492
493 public static final int icSigPreview1Tag = 0x70726531;
494
495
496
497
498 public static final int icSigPreview2Tag = 0x70726532;
499
500
501
502
503 public static final int icSigProfileDescriptionTag = 0x64657363;
504
505
506
507
508
509 public static final int icSigProfileSequenceDescTag = 0x70736571;
510
511
512
513
514
515 public static final int icSigPs2CRD0Tag = 0x70736430;
516
517
518
519
520 public static final int icSigPs2CRD1Tag = 0x70736431;
521
522
523
524
525 public static final int icSigPs2CRD2Tag = 0x70736432;
526
527
528
529
530 public static final int icSigPs2CRD3Tag = 0x70736433;
531
532
533
534
535 public static final int icSigPs2CSATag = 0x70733273;
536
537
538
539
540 public static final int icSigPs2RenderingIntentTag = 0x70733269;
541
542
543
544
545
546 public static final int icSigRedColorantTag = 0x7258595A;
547
548
549
550
551
552 public static final int icSigRedMatrixColumnTag = 0x7258595A;
553
554
555
556
557 public static final int icSigRedTRCTag = 0x72545243;
558
559
560
561
562 public static final int icSigScreeningDescTag = 0x73637264;
563
564
565
566
567 public static final int icSigScreeningTag = 0x7363726E;
568
569
570
571
572 public static final int icSigTechnologyTag = 0x74656368;
573
574
575
576
577 public static final int icSigUcrBgTag = 0x62666420;
578
579
580
581
582 public static final int icSigViewingCondDescTag = 0x76756564;
583
584
585
586
587 public static final int icSigViewingConditionsTag = 0x76696577;
588
589
590
591
592 public static final int icSigChromaticityTag = 0x6368726d;
593
594
595
596
597
598 public static final int icSigChromaticAdaptationTag = 0x63686164;
599
600
601
602
603
604 public static final int icSigColorantOrderTag = 0x636C726F;
605
606
607
608
609
610 public static final int icSigColorantTableTag = 0x636C7274;
611
612
613
614
615
616 public static final int icHdrSize = 0;
617
618
619
620
621 public static final int icHdrCmmId = 4;
622
623
624
625
626 public static final int icHdrVersion = 8;
627
628
629
630
631 public static final int icHdrDeviceClass = 12;
632
633
634
635
636 public static final int icHdrColorSpace = 16;
637
638
639
640
641 public static final int icHdrPcs = 20;
642
643
644
645
646 public static final int icHdrDate = 24;
647
648
649
650
651 public static final int icHdrMagic = 36;
652
653
654
655
656 public static final int icHdrPlatform = 40;
657
658
659
660
661 public static final int icHdrFlags = 44;
662
663
664
665
666 public static final int icHdrManufacturer = 48;
667
668
669
670
671 public static final int icHdrModel = 52;
672
673
674
675
676 public static final int icHdrAttributes = 56;
677
678
679
680
681 public static final int icHdrRenderingIntent = 64;
682
683
684
685
686 public static final int icHdrIlluminant = 68;
687
688
689
690
691 public static final int icHdrCreator = 80;
692
693
694
695
696
697 public static final int icHdrProfileID = 84;
698
699
700
701
702
703 public static final int icTagType = 0;
704
705
706
707
708 public static final int icTagReserved = 4;
709
710
711
712
713 public static final int icCurveCount = 8;
714
715
716
717
718 public static final int icCurveData = 12;
719
720
721
722
723 public static final int icXYZNumberX = 8;
724
725
726
727
728
729 ICC_Profile(long ID) {
730 this.ID = ID;
731 }
732
733
734
735
736
737
738 ICC_Profile(ProfileDeferralInfo pdi) {
739 this.deferralInfo = pdi;
740 this.profileActivator = new ProfileActivator() {
741 public void activate() throws ProfileDataException {
742 activateDeferredProfile();
743 }
744 };
745 ProfileDeferralMgr.registerDeferral(this.profileActivator);
746 }
747
748
749
750
751
752 protected void finalize () {
753 if (ID != 0) {
754 CMSManager.getModule().freeProfile(ID);
755 } else if (profileActivator != null) {
756 ProfileDeferralMgr.unregisterDeferral(profileActivator);
757 }
758 }
759
760
761
762
763
764
765
766
767
768
769 public static ICC_Profile getInstance(byte[] data) {
770 ICC_Profile thisProfile;
771
772 long theID;
773
774 if (ProfileDeferralMgr.deferring) {
775 ProfileDeferralMgr.activateProfiles();
776 }
777
778 try {
779 theID = CMSManager.getModule().loadProfile(data);
780 } catch (CMMException c) {
781 throw new IllegalArgumentException("Invalid ICC Profile Data");
782 }
783
784 try {
785 if ((getColorSpaceType (theID) == ColorSpace.TYPE_GRAY) &&
786 (getData (theID, icSigMediaWhitePointTag) != null) &&
787 (getData (theID, icSigGrayTRCTag) != null)) {
788 thisProfile = new ICC_ProfileGray (theID);
789 }
790 else if ((getColorSpaceType (theID) == ColorSpace.TYPE_RGB) &&
791 (getData (theID, icSigMediaWhitePointTag) != null) &&
792 (getData (theID, icSigRedColorantTag) != null) &&
793 (getData (theID, icSigGreenColorantTag) != null) &&
794 (getData (theID, icSigBlueColorantTag) != null) &&
795 (getData (theID, icSigRedTRCTag) != null) &&
796 (getData (theID, icSigGreenTRCTag) != null) &&
797 (getData (theID, icSigBlueTRCTag) != null)) {
798 thisProfile = new ICC_ProfileRGB (theID);
799 }
800 else {
801 thisProfile = new ICC_Profile (theID);
802 }
803 } catch (CMMException c) {
804 thisProfile = new ICC_Profile (theID);
805 }
806 return thisProfile;
807 }
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826 public static ICC_Profile getInstance (int cspace) {
827 ICC_Profile thisProfile = null;
828 String fileName;
829
830 switch (cspace) {
831 case ColorSpace.CS_sRGB:
832 synchronized(ICC_Profile.class) {
833 if (sRGBprofile == null) {
834
835
836
837
838
839 ProfileDeferralInfo pInfo =
840 new ProfileDeferralInfo("sRGB.pf",
841 ColorSpace.TYPE_RGB, 3,
842 CLASS_DISPLAY);
843 sRGBprofile = getDeferredInstance(pInfo);
844 }
845 thisProfile = sRGBprofile;
846 }
847
848 break;
849
850 case ColorSpace.CS_CIEXYZ:
851 synchronized(ICC_Profile.class) {
852 if (XYZprofile == null) {
853 ProfileDeferralInfo pInfo =
854 new ProfileDeferralInfo("CIEXYZ.pf",
855 ColorSpace.TYPE_XYZ, 3,
856 CLASS_DISPLAY);
857 XYZprofile = getDeferredInstance(pInfo);
858 }
859 thisProfile = XYZprofile;
860 }
861
862 break;
863
864 case ColorSpace.CS_PYCC:
865 synchronized(ICC_Profile.class) {
866 if (PYCCprofile == null) {
867 if (standardProfileExists("PYCC.pf"))
868 {
869 ProfileDeferralInfo pInfo =
870 new ProfileDeferralInfo("PYCC.pf",
871 ColorSpace.TYPE_3CLR, 3,
872 CLASS_DISPLAY);
873 PYCCprofile = getDeferredInstance(pInfo);
874 } else {
875 throw new IllegalArgumentException(
876 "Can't load standard profile: PYCC.pf");
877 }
878 }
879 thisProfile = PYCCprofile;
880 }
881
882 break;
883
884 case ColorSpace.CS_GRAY:
885 synchronized(ICC_Profile.class) {
886 if (GRAYprofile == null) {
887 ProfileDeferralInfo pInfo =
888 new ProfileDeferralInfo("GRAY.pf",
889 ColorSpace.TYPE_GRAY, 1,
890 CLASS_DISPLAY);
891 GRAYprofile = getDeferredInstance(pInfo);
892 }
893 thisProfile = GRAYprofile;
894 }
895
896 break;
897
898 case ColorSpace.CS_LINEAR_RGB:
899 synchronized(ICC_Profile.class) {
900 if (LINEAR_RGBprofile == null) {
901 ProfileDeferralInfo pInfo =
902 new ProfileDeferralInfo("LINEAR_RGB.pf",
903 ColorSpace.TYPE_RGB, 3,
904 CLASS_DISPLAY);
905 LINEAR_RGBprofile = getDeferredInstance(pInfo);
906 }
907 thisProfile = LINEAR_RGBprofile;
908 }
909
910 break;
911
912 default:
913 throw new IllegalArgumentException("Unknown color space");
914 }
915
916 return thisProfile;
917 }
918
919
920
921
922 private static ICC_Profile getStandardProfile(final String name) {
923
924 return (ICC_Profile) AccessController.doPrivileged(
925 new PrivilegedAction() {
926 public Object run() {
927 ICC_Profile p = null;
928 try {
929 p = getInstance (name);
930 } catch (IOException ex) {
931 throw new IllegalArgumentException(
932 "Can't load standard profile: " + name);
933 }
934 return p;
935 }
936 });
937 }
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965 public static ICC_Profile getInstance(String fileName) throws IOException {
966 ICC_Profile thisProfile;
967 FileInputStream fis = null;
968
969
970 File f = getProfileFile(fileName);
971 if (f != null) {
972 fis = new FileInputStream(f);
973 }
974 if (fis == null) {
975 throw new IOException("Cannot open file " + fileName);
976 }
977
978 thisProfile = getInstance(fis);
979
980 fis.close();
981
982 return thisProfile;
983 }
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001 public static ICC_Profile getInstance(InputStream s) throws IOException {
1002 byte profileData[];
1003
1004 if (s instanceof ProfileDeferralInfo) {
1005
1006 return getDeferredInstance((ProfileDeferralInfo) s);
1007 }
1008
1009 if ((profileData = getProfileDataFromStream(s)) == null) {
1010 throw new IllegalArgumentException("Invalid ICC Profile Data");
1011 }
1012
1013 return getInstance(profileData);
1014 }
1015
1016
1017 static byte[] getProfileDataFromStream(InputStream s) throws IOException {
1018 byte profileData[];
1019 int profileSize;
1020
1021 byte header[] = new byte[128];
1022 int bytestoread = 128;
1023 int bytesread = 0;
1024 int n;
1025
1026 while (bytestoread != 0) {
1027 if ((n = s.read(header, bytesread, bytestoread)) < 0) {
1028 return null;
1029 }
1030 bytesread += n;
1031 bytestoread -= n;
1032 }
1033 if (header[36] != 0x61 || header[37] != 0x63 ||
1034 header[38] != 0x73 || header[39] != 0x70) {
1035 return null;
1036 }
1037 profileSize = ((header[0] & 0xff) << 24) |
1038 ((header[1] & 0xff) << 16) |
1039 ((header[2] & 0xff) << 8) |
1040 (header[3] & 0xff);
1041 profileData = new byte[profileSize];
1042 System.arraycopy(header, 0, profileData, 0, 128);
1043 bytestoread = profileSize - 128;
1044 bytesread = 128;
1045 while (bytestoread != 0) {
1046 if ((n = s.read(profileData, bytesread, bytestoread)) < 0) {
1047 return null;
1048 }
1049 bytesread += n;
1050 bytestoread -= n;
1051 }
1052
1053 return profileData;
1054 }
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069 static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi) {
1070 if (!ProfileDeferralMgr.deferring) {
1071 return getStandardProfile(pdi.filename);
1072 }
1073 if (pdi.colorSpaceType == ColorSpace.TYPE_RGB) {
1074 return new ICC_ProfileRGB(pdi);
1075 } else if (pdi.colorSpaceType == ColorSpace.TYPE_GRAY) {
1076 return new ICC_ProfileGray(pdi);
1077 } else {
1078 return new ICC_Profile(pdi);
1079 }
1080 }
1081
1082
1083 void activateDeferredProfile() throws ProfileDataException {
1084 byte profileData[];
1085 FileInputStream fis;
1086 final String fileName = deferralInfo.filename;
1087
1088 profileActivator = null;
1089 deferralInfo = null;
1090 PrivilegedAction<FileInputStream> pa = new PrivilegedAction<FileInputStream>() {
1091 public FileInputStream run() {
1092 File f = getStandardProfileFile(fileName);
1093 if (f != null) {
1094 try {
1095 return new FileInputStream(f);
1096 } catch (FileNotFoundException e) {}
1097 }
1098 return null;
1099 }
1100 };
1101 if ((fis = AccessController.doPrivileged(pa)) == null) {
1102 throw new ProfileDataException("Cannot open file " + fileName);
1103 }
1104 try {
1105 profileData = getProfileDataFromStream(fis);
1106 fis.close();
1107 }
1108 catch (IOException e) {
1109 ProfileDataException pde = new
1110 ProfileDataException("Invalid ICC Profile Data" + fileName);
1111 pde.initCause(e);
1112 throw pde;
1113 }
1114 if (profileData == null) {
1115 throw new ProfileDataException("Invalid ICC Profile Data" +
1116 fileName);
1117 }
1118 try {
1119 ID = CMSManager.getModule().loadProfile(profileData);
1120 } catch (CMMException c) {
1121 ProfileDataException pde = new
1122 ProfileDataException("Invalid ICC Profile Data" + fileName);
1123 pde.initCause(c);
1124 throw pde;
1125 }
1126 }
1127
1128
1129
1130
1131
1132
1133 public int getMajorVersion() {
1134 byte[] theHeader;
1135
1136 theHeader = getData(icSigHead);
1137
1138
1139 return (int) theHeader[8];
1140 }
1141
1142
1143
1144
1145
1146 public int getMinorVersion() {
1147 byte[] theHeader;
1148
1149 theHeader = getData(icSigHead);
1150
1151
1152 return (int) theHeader[9];
1153 }
1154
1155
1156
1157
1158
1159 public int getProfileClass() {
1160 byte[] theHeader;
1161 int theClassSig, theClass;
1162
1163 if (deferralInfo != null) {
1164 return deferralInfo.profileClass;
1165
1166
1167
1168 }
1169
1170 theHeader = getData(icSigHead);
1171
1172 theClassSig = intFromBigEndian (theHeader, icHdrDeviceClass);
1173
1174 switch (theClassSig) {
1175 case icSigInputClass:
1176 theClass = CLASS_INPUT;
1177 break;
1178
1179 case icSigDisplayClass:
1180 theClass = CLASS_DISPLAY;
1181 break;
1182
1183 case icSigOutputClass:
1184 theClass = CLASS_OUTPUT;
1185 break;
1186
1187 case icSigLinkClass:
1188 theClass = CLASS_DEVICELINK;
1189 break;
1190
1191 case icSigColorSpaceClass:
1192 theClass = CLASS_COLORSPACECONVERSION;
1193 break;
1194
1195 case icSigAbstractClass:
1196 theClass = CLASS_ABSTRACT;
1197 break;
1198
1199 case icSigNamedColorClass:
1200 theClass = CLASS_NAMEDCOLOR;
1201 break;
1202
1203 default:
1204 throw new IllegalArgumentException("Unknown profile class");
1205 }
1206
1207 return theClass;
1208 }
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222 public int getColorSpaceType() {
1223 if (deferralInfo != null) {
1224 return deferralInfo.colorSpaceType;
1225
1226
1227
1228 }
1229 return getColorSpaceType(ID);
1230 }
1231
1232 static int getColorSpaceType(long profileID) {
1233 byte[] theHeader;
1234 int theColorSpaceSig, theColorSpace;
1235
1236 theHeader = getData(profileID, icSigHead);
1237 theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace);
1238 theColorSpace = iccCStoJCS (theColorSpaceSig);
1239 return theColorSpace;
1240 }
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254 public int getPCSType() {
1255 if (ProfileDeferralMgr.deferring) {
1256 ProfileDeferralMgr.activateProfiles();
1257 }
1258 return getPCSType(ID);
1259 }
1260
1261
1262 static int getPCSType(long profileID) {
1263 byte[] theHeader;
1264 int thePCSSig, thePCS;
1265
1266 theHeader = getData(profileID, icSigHead);
1267 thePCSSig = intFromBigEndian(theHeader, icHdrPcs);
1268 thePCS = iccCStoJCS(thePCSSig);
1269 return thePCS;
1270 }
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281 public void write(String fileName) throws IOException {
1282 FileOutputStream outputFile;
1283 byte profileData[];
1284
1285 profileData = getData();
1286
1287 outputFile = new FileOutputStream(fileName);
1288 outputFile.write(profileData);
1289 outputFile.close ();
1290 }
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301 public void write(OutputStream s) throws IOException {
1302 byte profileData[];
1303
1304 profileData = getData();
1305
1306 s.write(profileData);
1307 }
1308
1309
1310
1311
1312
1313
1314
1315 public byte[] getData() {
1316 int profileSize;
1317 byte[] profileData;
1318
1319 if (ProfileDeferralMgr.deferring) {
1320 ProfileDeferralMgr.activateProfiles();
1321 }
1322
1323 PCMM mdl = CMSManager.getModule();
1324
1325
1326 profileSize = mdl.getProfileSize(ID);
1327
1328 profileData = new byte [profileSize];
1329
1330
1331 mdl.getProfileData(ID, profileData);
1332
1333 return profileData;
1334 }
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352 public byte[] getData(int tagSignature) {
1353
1354 if (ProfileDeferralMgr.deferring) {
1355 ProfileDeferralMgr.activateProfiles();
1356 }
1357
1358 return getData(ID, tagSignature);
1359 }
1360
1361
1362 static byte[] getData(long profileID, int tagSignature) {
1363 int tagSize;
1364 byte[] tagData;
1365
1366 try {
1367 PCMM mdl = CMSManager.getModule();
1368
1369
1370 tagSize = mdl.getTagSize(profileID, tagSignature);
1371
1372 tagData = new byte[tagSize];
1373
1374
1375 mdl.getTagData(profileID, tagSignature, tagData);
1376 } catch(CMMException c) {
1377 tagData = null;
1378 }
1379
1380 return tagData;
1381 }
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400 public void setData(int tagSignature, byte[] tagData) {
1401
1402 if (ProfileDeferralMgr.deferring) {
1403 ProfileDeferralMgr.activateProfiles();
1404 }
1405
1406 CMSManager.getModule().setTagData(ID, tagSignature, tagData);
1407 }
1408
1409
1410
1411
1412
1413
1414 void setRenderingIntent(int renderingIntent) {
1415 byte[] theHeader = getData(icSigHead);
1416
1417 intToBigEndian (renderingIntent, theHeader, icHdrRenderingIntent);
1418
1419 setData (icSigHead, theHeader);
1420 }
1421
1422
1423
1424
1425
1426
1427
1428
1429 int getRenderingIntent() {
1430 byte[] theHeader = getData(icSigHead);
1431
1432
1433 int renderingIntent = intFromBigEndian(theHeader, icHdrRenderingIntent);
1434
1435 return renderingIntent;
1436 }
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450 public int getNumComponents() {
1451 byte[] theHeader;
1452 int theColorSpaceSig, theNumComponents;
1453
1454 if (deferralInfo != null) {
1455 return deferralInfo.numComponents;
1456
1457
1458
1459 }
1460 theHeader = getData(icSigHead);
1461
1462 theColorSpaceSig = intFromBigEndian (theHeader, icHdrColorSpace);
1463
1464 switch (theColorSpaceSig) {
1465 case icSigGrayData:
1466 theNumComponents = 1;
1467 break;
1468
1469 case icSigSpace2CLR:
1470 theNumComponents = 2;
1471 break;
1472
1473 case icSigXYZData:
1474 case icSigLabData:
1475 case icSigLuvData:
1476 case icSigYCbCrData:
1477 case icSigYxyData:
1478 case icSigRgbData:
1479 case icSigHsvData:
1480 case icSigHlsData:
1481 case icSigCmyData:
1482 case icSigSpace3CLR:
1483 theNumComponents = 3;
1484 break;
1485
1486 case icSigCmykData:
1487 case icSigSpace4CLR:
1488 theNumComponents = 4;
1489 break;
1490
1491 case icSigSpace5CLR:
1492 theNumComponents = 5;
1493 break;
1494
1495 case icSigSpace6CLR:
1496 theNumComponents = 6;
1497 break;
1498
1499 case icSigSpace7CLR:
1500 theNumComponents = 7;
1501 break;
1502
1503 case icSigSpace8CLR:
1504 theNumComponents = 8;
1505 break;
1506
1507 case icSigSpace9CLR:
1508 theNumComponents = 9;
1509 break;
1510
1511 case icSigSpaceACLR:
1512 theNumComponents = 10;
1513 break;
1514
1515 case icSigSpaceBCLR:
1516 theNumComponents = 11;
1517 break;
1518
1519 case icSigSpaceCCLR:
1520 theNumComponents = 12;
1521 break;
1522
1523 case icSigSpaceDCLR:
1524 theNumComponents = 13;
1525 break;
1526
1527 case icSigSpaceECLR:
1528 theNumComponents = 14;
1529 break;
1530
1531 case icSigSpaceFCLR:
1532 theNumComponents = 15;
1533 break;
1534
1535 default:
1536 throw new ProfileDataException ("invalid ICC color space");
1537 }
1538
1539 return theNumComponents;
1540 }
1541
1542
1543
1544
1545
1546
1547 float[] getMediaWhitePoint() {
1548 return getXYZTag(icSigMediaWhitePointTag);
1549
1550 }
1551
1552
1553
1554
1555
1556
1557 float[] getXYZTag(int theTagSignature) {
1558 byte[] theData;
1559 float[] theXYZNumber;
1560 int i1, i2, theS15Fixed16;
1561
1562 theData = getData(theTagSignature);
1563
1564
1565
1566 theXYZNumber = new float [3];
1567
1568
1569 for (i1 = 0, i2 = icXYZNumberX; i1 < 3; i1++, i2 += 4) {
1570 theS15Fixed16 = intFromBigEndian(theData, i2);
1571 theXYZNumber [i1] = ((float) theS15Fixed16) / 65536.0f;
1572 }
1573 return theXYZNumber;
1574 }
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588 float getGamma(int theTagSignature) {
1589 byte[] theTRCData;
1590 float theGamma;
1591 int theU8Fixed8;
1592
1593 theTRCData = getData(theTagSignature);
1594
1595
1596
1597 if (intFromBigEndian (theTRCData, icCurveCount) != 1) {
1598 throw new ProfileDataException ("TRC is not a gamma");
1599 }
1600
1601
1602 theU8Fixed8 = (shortFromBigEndian(theTRCData, icCurveData)) & 0xffff;
1603
1604 theGamma = ((float) theU8Fixed8) / 256.0f;
1605
1606 return theGamma;
1607 }
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630 short[] getTRC(int theTagSignature) {
1631 byte[] theTRCData;
1632 short[] theTRC;
1633 int i1, i2, nElements, theU8Fixed8;
1634
1635 theTRCData = getData(theTagSignature);
1636
1637
1638
1639 nElements = intFromBigEndian(theTRCData, icCurveCount);
1640
1641 if (nElements == 1) {
1642 throw new ProfileDataException("TRC is not a table");
1643 }
1644
1645
1646 theTRC = new short [nElements];
1647
1648 for (i1 = 0, i2 = icCurveData; i1 < nElements; i1++, i2 += 2) {
1649 theTRC[i1] = shortFromBigEndian(theTRCData, i2);
1650 }
1651
1652 return theTRC;
1653 }
1654
1655
1656
1657 static int iccCStoJCS(int theColorSpaceSig) {
1658 int theColorSpace;
1659
1660 switch (theColorSpaceSig) {
1661 case icSigXYZData:
1662 theColorSpace = ColorSpace.TYPE_XYZ;
1663 break;
1664
1665 case icSigLabData:
1666 theColorSpace = ColorSpace.TYPE_Lab;
1667 break;
1668
1669 case icSigLuvData:
1670 theColorSpace = ColorSpace.TYPE_Luv;
1671 break;
1672
1673 case icSigYCbCrData:
1674 theColorSpace = ColorSpace.TYPE_YCbCr;
1675 break;
1676
1677 case icSigYxyData:
1678 theColorSpace = ColorSpace.TYPE_Yxy;
1679 break;
1680
1681 case icSigRgbData:
1682 theColorSpace = ColorSpace.TYPE_RGB;
1683 break;
1684
1685 case icSigGrayData:
1686 theColorSpace = ColorSpace.TYPE_GRAY;
1687 break;
1688
1689 case icSigHsvData:
1690 theColorSpace = ColorSpace.TYPE_HSV;
1691 break;
1692
1693 case icSigHlsData:
1694 theColorSpace = ColorSpace.TYPE_HLS;
1695 break;
1696
1697 case icSigCmykData:
1698 theColorSpace = ColorSpace.TYPE_CMYK;
1699 break;
1700
1701 case icSigCmyData:
1702 theColorSpace = ColorSpace.TYPE_CMY;
1703 break;
1704
1705 case icSigSpace2CLR:
1706 theColorSpace = ColorSpace.TYPE_2CLR;
1707 break;
1708
1709 case icSigSpace3CLR:
1710 theColorSpace = ColorSpace.TYPE_3CLR;
1711 break;
1712
1713 case icSigSpace4CLR:
1714 theColorSpace = ColorSpace.TYPE_4CLR;
1715 break;
1716
1717 case icSigSpace5CLR:
1718 theColorSpace = ColorSpace.TYPE_5CLR;
1719 break;
1720
1721 case icSigSpace6CLR:
1722 theColorSpace = ColorSpace.TYPE_6CLR;
1723 break;
1724
1725 case icSigSpace7CLR:
1726 theColorSpace = ColorSpace.TYPE_7CLR;
1727 break;
1728
1729 case icSigSpace8CLR:
1730 theColorSpace = ColorSpace.TYPE_8CLR;
1731 break;
1732
1733 case icSigSpace9CLR:
1734 theColorSpace = ColorSpace.TYPE_9CLR;
1735 break;
1736
1737 case icSigSpaceACLR:
1738 theColorSpace = ColorSpace.TYPE_ACLR;
1739 break;
1740
1741 case icSigSpaceBCLR:
1742 theColorSpace = ColorSpace.TYPE_BCLR;
1743 break;
1744
1745 case icSigSpaceCCLR:
1746 theColorSpace = ColorSpace.TYPE_CCLR;
1747 break;
1748
1749 case icSigSpaceDCLR:
1750 theColorSpace = ColorSpace.TYPE_DCLR;
1751 break;
1752
1753 case icSigSpaceECLR:
1754 theColorSpace = ColorSpace.TYPE_ECLR;
1755 break;
1756
1757 case icSigSpaceFCLR:
1758 theColorSpace = ColorSpace.TYPE_FCLR;
1759 break;
1760
1761 default:
1762 throw new IllegalArgumentException ("Unknown color space");
1763 }
1764
1765 return theColorSpace;
1766 }
1767
1768
1769 static int intFromBigEndian(byte[] array, int index) {
1770 return (((array[index] & 0xff) << 24) |
1771 ((array[index+1] & 0xff) << 16) |
1772 ((array[index+2] & 0xff) << 8) |
1773 (array[index+3] & 0xff));
1774 }
1775
1776
1777 static void intToBigEndian(int value, byte[] array, int index) {
1778 array[index] = (byte) (value >> 24);
1779 array[index+1] = (byte) (value >> 16);
1780 array[index+2] = (byte) (value >> 8);
1781 array[index+3] = (byte) (value);
1782 }
1783
1784
1785 static short shortFromBigEndian(byte[] array, int index) {
1786 return (short) (((array[index] & 0xff) << 8) |
1787 (array[index+1] & 0xff));
1788 }
1789
1790
1791 static void shortToBigEndian(short value, byte[] array, int index) {
1792 array[index] = (byte) (value >> 8);
1793 array[index+1] = (byte) (value);
1794 }
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806 private static File getProfileFile(String fileName) {
1807 String path, dir, fullPath;
1808
1809 File f = new File(fileName);
1810 if (f.isAbsolute()) {
1811
1812
1813 return f.isFile() ? f : null;
1814 }
1815 if ((!f.isFile()) &&
1816 ((path = System.getProperty("java.iccprofile.path")) != null)){
1817
1818 StringTokenizer st =
1819 new StringTokenizer(path, File.pathSeparator);
1820 while (st.hasMoreTokens() && ((f == null) || (!f.isFile()))) {
1821 dir = st.nextToken();
1822 fullPath = dir + File.separatorChar + fileName;
1823 f = new File(fullPath);
1824 if (!isChildOf(f, dir)) {
1825 f = null;
1826 }
1827 }
1828 }
1829
1830 if (((f == null) || (!f.isFile())) &&
1831 ((path = System.getProperty("java.class.path")) != null)) {
1832
1833 StringTokenizer st =
1834 new StringTokenizer(path, File.pathSeparator);
1835 while (st.hasMoreTokens() && ((f == null) || (!f.isFile()))) {
1836 dir = st.nextToken();
1837 fullPath = dir + File.separatorChar + fileName;
1838 f = new File(fullPath);
1839 }
1840 }
1841
1842 if ((f == null) || (!f.isFile())) {
1843
1844 f = getStandardProfileFile(fileName);
1845 }
1846 if (f != null && f.isFile()) {
1847 return f;
1848 }
1849 return null;
1850 }
1851
1852
1853
1854
1855
1856
1857
1858 private static File getStandardProfileFile(String fileName) {
1859 String dir = System.getProperty("java.home") +
1860 File.separatorChar + "lib" + File.separatorChar + "cmm";
1861 String fullPath = dir + File.separatorChar + fileName;
1862 File f = new File(fullPath);
1863 return (f.isFile() && isChildOf(f, dir)) ? f : null;
1864 }
1865
1866
1867
1868
1869 private static boolean isChildOf(File f, String dirName) {
1870 try {
1871 File dir = new File(dirName);
1872 String canonicalDirName = dir.getCanonicalPath();
1873 if (!canonicalDirName.endsWith(File.separator)) {
1874 canonicalDirName += File.separator;
1875 }
1876 String canonicalFileName = f.getCanonicalPath();
1877 return canonicalFileName.startsWith(canonicalDirName);
1878 } catch (IOException e) {
1879
1880
1881
1882 return false;
1883 }
1884 }
1885
1886
1887
1888
1889 private static boolean standardProfileExists(final String fileName) {
1890 return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
1891 public Boolean run() {
1892 return getStandardProfileFile(fileName) != null;
1893 }
1894 });
1895 }
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933 private int iccProfileSerializedDataVersion = 1;
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960 private void writeObject(ObjectOutputStream s)
1961 throws IOException
1962 {
1963 s.defaultWriteObject();
1964
1965 String csName = null;
1966 if (this == sRGBprofile) {
1967 csName = "CS_sRGB";
1968 } else if (this == XYZprofile) {
1969 csName = "CS_CIEXYZ";
1970 } else if (this == PYCCprofile) {
1971 csName = "CS_PYCC";
1972 } else if (this == GRAYprofile) {
1973 csName = "CS_GRAY";
1974 } else if (this == LINEAR_RGBprofile) {
1975 csName = "CS_LINEAR_RGB";
1976 }
1977
1978
1979
1980
1981
1982 byte[] data = null;
1983 if (csName == null) {
1984
1985 data = getData();
1986 }
1987
1988 s.writeObject(csName);
1989 s.writeObject(data);
1990 }
1991
1992
1993
1994 private transient ICC_Profile resolvedDeserializedProfile;
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028 private void readObject(ObjectInputStream s)
2029 throws IOException, ClassNotFoundException
2030 {
2031 s.defaultReadObject();
2032
2033 String csName = (String)s.readObject();
2034 byte[] data = (byte[])s.readObject();
2035
2036 int cspace = 0;
2037 boolean isKnownPredefinedCS = false;
2038 if (csName != null) {
2039 isKnownPredefinedCS = true;
2040 if (csName.equals("CS_sRGB")) {
2041 cspace = ColorSpace.CS_sRGB;
2042 } else if (csName.equals("CS_CIEXYZ")) {
2043 cspace = ColorSpace.CS_CIEXYZ;
2044 } else if (csName.equals("CS_PYCC")) {
2045 cspace = ColorSpace.CS_PYCC;
2046 } else if (csName.equals("CS_GRAY")) {
2047 cspace = ColorSpace.CS_GRAY;
2048 } else if (csName.equals("CS_LINEAR_RGB")) {
2049 cspace = ColorSpace.CS_LINEAR_RGB;
2050 } else {
2051 isKnownPredefinedCS = false;
2052 }
2053 }
2054
2055 if (isKnownPredefinedCS) {
2056 resolvedDeserializedProfile = getInstance(cspace);
2057 } else {
2058 resolvedDeserializedProfile = getInstance(data);
2059 }
2060 }
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070 protected Object readResolve() throws ObjectStreamException {
2071 return resolvedDeserializedProfile;
2072 }
2073 }